﻿#include "Contra.h"


CContra::CContra()
{
	_isRight = true;
	_isJump = true;
	_isMove = true;
	_layAndFall = false;
	_isDown = 0;
	_dwFallTime = 0;
	_dwStartFall = 0;
	frame_start = GetTickCount();
	tick_per_frame = TIMESTART;
	_isSwim = false;
	//gun
	_gun = false;
	_gun_bullet = CTimer(200);
	_gun_render = CTimer(600);
	_levelBullet = 7;
	
	//alive
	_health = 7;
	_botGround = NULL;
}

int CContra::ContraLoadSound(Sound isound)
{
	_sound = isound;
	
	_CSound = _sound.LoadSound(L"resources\\Sound\\Bullet_Contra_01.wav");
	if (_CSound == NULL)
		return 0;

	return 1;
}

void CContra::LoadResource(LPDIRECT3DDEVICE9 d3ddv, LPD3DXSPRITE &SpriteHandler, HINSTANCE hInstance, HWND hWnd)
{
	_vectorX = 0.0f;
	_vectorY = 0.0f;
	_gun = true;

	_rSprite = new CSprite(SpriteHandler, L"resources\\contraright.png", CONTRAWIDTH, CONTRAHEIGHT, 40, 10, D3DCOLOR_XRGB(255, 255, 255));
	_lSprite = new CSprite(SpriteHandler, L"resources\\contraleft.png", CONTRAWIDTH, CONTRAHEIGHT, 40, 10, D3DCOLOR_XRGB(255, 255, 255));
	_bossLight = new CSprite(SpriteHandler, L"resources\\bosslight1.png", FRAMEWIDTH, FRAMEHEIGHT, 3, 3, D3DCOLOR_XRGB(255, 255, 255));

	_sprite_bullet = new CSprite(SpriteHandler, L"resources\\bullet.png", 28, 28, 11, 11, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[0] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_01.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[1] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_02.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[2] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_03.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[3] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_04.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[4] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_05.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[5] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_06.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[6] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_07.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));
	_sprite_bullet_fire[7] = new CSprite(SpriteHandler, L"resources\\bulletfire\\bulletfire_08.png", 32, 12, 1, 1, D3DCOLOR_XRGB(255, 255, 0));

	_x = FRAMEWIDTH + FRAMEWIDTH / 2;
	_groundY = VIEW_PORT_Y - SCREEN_HEIGHT + FRAMEHEIGHT/2;
	_y = GROUNDY + FRAMEHEIGHT * 2;
	
	InitKeyboard(hInstance, hWnd);
}

void CContra::ProcessInput()
{
	if (_isJump || !_isFall || (_isFall && _dwFallTime > FALL_DELAY_TIME))
	{
		_isDown = 0;
		if (IsKeyDown(DIK_S))
		{
			_isDown = 1;
		}
		else
		{
			if (IsKeyDown(DIK_W))
				_isDown = -1;
		}

		if (IsKeyDown(DIK_D))
		{
			if (_isSwim && _isDown == 1)
			{
				_vectorX = 0.0f;
			}
			else
			{
				_vectorX = MOVING_SPEED;
				_isRight = true;
				_isMove = true;
			}
		}
		else
		{
			if (IsKeyDown(DIK_A))
			{
				if (_isSwim && _isDown == 1)
				{
					_vectorX = 0.0f;
				}
				else
				{
					_vectorX = -MOVING_SPEED;
					_isRight = false;
					_isMove = true;
				}
			}
			else
			{
				//if (!_isJump)
				{
					_vectorX = 0.0f;
					_isMove = false;
				}
			}
		}
		
	}

	//Gun
	if (IsKeyDown(DIK_J))
	{
		if (_levelBullet == 8)
			_levelBullet = 7;
		switch(_levelBullet)
		{
			case 3:
				if (_gun_bullet.ClockTrue())
				{
					ContraGun();
				}
				break;
			case 7: // L the keep
				if (_gun_bullet.ClockTrue() && _gunContra.GunAddL(1))
				{
					ContraGun();
				}
				break;
		}
	}
}

void CContra::ContraGun()
{
	_gun = true;
	switch (_levelBullet)
	{
		case 4:
			_sprite_bullet->Next(_levelBullet - 1, 3);
			break;
		case 6:

			break;
		case 7:
			_sprite_bullet_fire[0]->Next(0, 1);
			break;
		case 8:
			_sprite_bullet_fire[0]->Next(0, 1);
			break;
		default:
			_sprite_bullet->Next(_levelBullet, 1);
			break;

	}

	_sound.PlaySound(_CSound);
	_gunContra.GunContra_Run(_isJump, _isRight, _isDown, _isMove, _levelBullet, _x, _y, _rSprite, _lSprite);
}

void CContra::Contra_Die()
{
	if (_isRight)
	{
		if (_y > _groundY)
		{
			_vectorX = -MOVING_SPEED / 2;
			_rSprite->Next(14, 4);
		}
		else
		{
			_vectorX = 0;
			_rSprite->Next(18, 1);
		}
	}
	else
	{
		if (_y > _groundY)
		{
			_vectorX = MOVING_SPEED / 2;
			_lSprite->Next(12, 4);
		}
		else
		{
			_vectorX = 0;
			_lSprite->Next(11, 1);
		}
	}
}

void CContra::OnKeyUp(int KeyCode)
{
	switch (KeyCode)
	{
		case DIK_J:
			if (!_gun_bullet.ClockTrue())
			{
				switch (_levelBullet)
				{
					case 7:
						_levelBullet = 8;
						ContraGun();
						break;
					case 8:
						_levelBullet = 7;
						ContraGun();
						break;
				}		
			}
			break;

		//test die
		case DIK_N:
		{
			_health = 0;
			_vectorY += JUMP_VELOCITY_BOOST;			// start jump if is not "on-air"j
			_isJump = false;
		}
			break;
		case DIK_M:
		{
			_health = 7;
			_y = GROUNDY + FRAMEHEIGHT * 2;
		}
			break;

		//test bullet
		case DIK_0:
			_levelBullet = 0;
			break;
		case DIK_1:
			_levelBullet = 1;
			break;
		case DIK_2:
			_levelBullet = 2;
			break;
		case DIK_3:
			_levelBullet = 3;
			break;
		case DIK_4:
			_levelBullet = 4;
			break;
		case DIK_5:
			_levelBullet = 5;
			break;
		case DIK_6:
			_levelBullet = 6;
			break;
		case DIK_7:
			_levelBullet = 7;
			break;
		case DIK_8:
			_levelBullet = 8;
			break;
		case DIK_9:
			_levelBullet = 9;
			break;
		case DIK_P:
			_levelBullet = 10;
			break;
	}
}

void CContra::OnKeyDown(int KeyCode)
{
	switch (KeyCode)
	{
	case DIK_L:
		if (_isSwim || _health == 0)
			break;
		if (!_isJump && !_isFall)
		{
			if (!_isMove && _isDown == 1)
			{
				//neu ben duoi co object
				if (_layAndFall)
				{
					_groundY = FRAMEHEIGHT;
					_isFall = true;
				}
			}
			else
			{
				_vectorY += JUMP_VELOCITY_BOOST;			// start jump if is not "on-air"j
				_isJump = true;
			}
		}

		break;
	case DIK_J:
		if (_gun_bullet.ClockTrue() && _levelBullet != 7 && _levelBullet != 8)
		{
			ContraGun();
		}

		break;
	}
}

void CContra::Contra_Run()
{
	ProcessKeyBoard();
	if (_health > 0)
	{
		ProcessInput();
	}

	_x += _vectorX;
	_y += _vectorY;

	vpx = _x - SCREEN_WIDTH / 2;
	vpy = SCREEN_HEIGHT;
	if (vpx <= 0)
	{
		vpx = 0;
	//	_x -= _vectorX / 4;
	}
	if (vpx >= GAMEWORLDWIDTH - SCREEN_WIDTH)
	{
		vpx = GAMEWORLDWIDTH - SCREEN_WIDTH;
		_x -= _vectorX / 4;
	}

	if (_x >= GAMEWORLDWIDTH - FRAMEWIDTH - 100)
	{
		_x = GAMEWORLDWIDTH - FRAMEWIDTH - 100;
	}
	if (_x <= 0)
	{
		_x = 0;
	}

	if (!_isJump && _isFall)
	{
		if (_dwStartFall == 0)
			StartFall();
		else
			ProcessFall();
	}

	if (_y > _groundY)
		_vectorY -= FALLDOWN_VELOCITY_DECREASE;
	else
	{
		_y = _groundY;
		_vectorY = 0;
		_isJump = false;

		EndFall();
		_isFall = false;
	}

	if (_health >0 && _y == VIEW_PORT_Y - SCREEN_HEIGHT + FRAMEHEIGHT/2)
	{
		_isJump = false;
		_isFall = false;
		EndFall();
		_health = 0;
		_vectorY = JUMP_VELOCITY_BOOST;
	}

}

void CContra::Update()
{
	if (_health > 0)
	{
		if (_isRight)
		{
			if (_isJump)
			{
				_rSprite->Next(10, 4);
			}
			else if (_isFall)
			{
				_rSprite->Next(3, 1);
			}
			else if (_isSwim)
			{
				if (_isDown == 1)
					_rSprite->Next(28, 1);
				else
					_rSprite->Next(26, 1);
			}
			else
			{
				if (_isMove)
				{
					if (_isDown == 1)
					{
						_rSprite->Next(23, 3);
					}
					else
					{
						if (_isDown == -1)
						{
							_rSprite->Next(20, 3);
						}
						else
						{
							if (_gun)
								_rSprite->Next(30, 5);
							else
								_rSprite->Previous(0, 5);
						}
					}
				}
				else
				{
					if (_isDown == 1)
					{
						_rSprite->Next(7, 1);
					}
					else
					{
						if (_isDown == -1)
						{
							_rSprite->Next(8, 1);
						}
						else
						{
							_rSprite->Next(5, 1);
						}
					}
				}
			}
		}
		else
		{
			if (_isJump)
			{
				_lSprite->Next(16, 4);
			}
			else if (_isFall)
			{
				_lSprite->Next(5, 1);
			}
			else if (_isSwim)
			{
				if (_isDown == 1)
					_lSprite->Next(21, 1);
				else
					_lSprite->Next(23, 1);
			}
			else
			{
				if (_isMove)
				{
					if (_isDown == 1)
					{
						_lSprite->Next(24, 3);
					}
					else
					{
						if (_isDown == -1)
						{
							_lSprite->Next(27, 3);
						}
						else
						{
							if (_gun)
								_lSprite->Next(35, 5);
							else
								_lSprite->Previous(5, 5);
						}
					}
				}
				else
				{
					if (_isDown == 1)
					{
						_lSprite->Next(2, 1);
					}
					else
					{
						if (_isDown == -1)
						{
							_lSprite->Next(0, 1);
						}
						else
						{
							_lSprite->Next(4, 1);
						}
					}
				}
			}
		}
	}
	else
	{
		Contra_Die();
	}
	
}

void CContra::Render()
{
	DWORD now = GetTickCount();
	if (now - frame_start >= tick_per_frame)
	{
		frame_start = now;
		Update();
		_bossLight->Next();		
	}

	CCamera::getInstance()->Update(_x, _y);

	// light on the boss1
	if (_x >= GAMEWORLDWIDTH - SCREEN_WIDTH)
		_bossLight->Render(FRAMEWIDTH / 2 + FRAMEWIDTH * 100 + FRAMEWIDTH / 2 + 5, FRAMEHEIGHT + FRAMEHEIGHT / 2 + FRAMEHEIGHT - FRAMEHEIGHT / 2);
	
	//-----------------
	//Gun contra
	switch (_levelBullet)
	{
	case 7:
		_gunContra.Draw(_sprite_bullet_fire[0]);
		break;
	case 8:
		_gunContra.Draw(_sprite_bullet_fire[0]);
		break;
	default:
		_gunContra.Draw(_sprite_bullet);
		break;
	}
	if (_gun)
	{
		if (_gun_render.ClockTrue())
		{
			_gun = false;
		}
	}


	//render contra
	//sua lai render ve giua
	if (_isRight)
	{	
		_rSprite->Render(_x, _y);
	}
	else
	{
		_lSprite->Render(_x, _y);
	}
}

void CContra::Contra_End()
{
	if (_rSprite != NULL)
		delete _rSprite;

	if (_lSprite != NULL)
		delete _lSprite;

	if (_bossLight != NULL)
		delete _bossLight;

	if (_CSound != NULL)
		delete _CSound;

	_gunContra.GunContra_End();
}

Box CContra::GetBox()
{
	Box box;

	if (_isJump)
	{
		box.iY = _y - 54;
		box.iX = _x + 15;
		box.iHeight = 42;
		box.iWidth = 40;
	}
	else if (_isFall)
	{
		box.iY = _y - 24;
		box.iX = _x + 11;
		box.iHeight = 72;
		box.iWidth = 48;
	}
	else if (_isSwim)
	{
		box.iY = _y - 64;
		box.iX = _x + 11;
		box.iHeight = 32;
		box.iWidth = 48;
	}
	else
	{
		if (_isMove)
		{
			box.iY = _y - 24;
			box.iX = _x + 11;
			box.iHeight = 72;
			box.iWidth = 48;
		}
		else
		{
			if (_isDown == 1)
			{
				box.iY = _y - 62;
				box.iX = _x;
				box.iHeight = 34;
				box.iWidth = 70;
			}
			else
			{
				if (_isDown == -1)
				{
					box.iY = _y;
					box.iX = _x + 15;
					box.iHeight = 92;
					box.iWidth = 32;
				}
				else
				{
					box.iY = _y - 24;
					box.iX = _x + 11;
					box.iHeight = 72;
					box.iWidth = 48;
				}
			}
		}
	}

	//chuyen toa do ve goc tren, ben trai
	box.SetPosition(box.iX - FRAMEWIDTH / 2, box.iY + FRAMEHEIGHT);
	box.SetVelocity(_vectorX, _vectorY);
	return box;
}

void CContra::TopLandColl(){ }
void CContra::BotLandColl(int groundY)
{
	_groundY = groundY;
	_isFall = false;
	_isSwim = false;
}
void CContra::TopWaterColl(){ }
void CContra::BotWaterColl(int groundY)
{
	_groundY = groundY;
	_isFall = false;
	_isJump = false;
	_isSwim = true;
}
void CContra::LeftColl(int groundY, int contraX)
{
	_x = contraX;
	_groundY = groundY;
	_isFall = false;
	if (_isSwim)
		_isSwim = false;
}
void CContra::RightColl(int groundY, int contraX)
{
	_x = contraX;
	_groundY = groundY;
	_isFall = false;
	if (_isSwim)
		_isSwim = false;
}
void CContra::NoColl(int groundY)
{
	_groundY = groundY;
	_isFall = true;
}

void CContra::HandleCollisionOnMap(std::vector<CMapGround*> listObject)
{
	Box contra = GetBox();

	//bien bool xac dinh contra o trong mien va cham
	bool inDomain = false;
	//
	bool layAndFall = false;
	
	//contra chua thoat ra khoi vung dat va cham truoc do
	if (_botGround != NULL
		&& contra.iX + contra.iWidth / 2 > _botGround->GetBox().iX
		&& contra.iX + contra.iWidth / 2 < _botGround->GetBox().iX + _botGround->GetBox().iWidth
		&& contra.iY - contra.iHeight <= _botGround->GetBox().iY
		&& contra.iY - contra.iHeight > _botGround->GetBox().iY - _botGround->GetBox().iHeight)
		inDomain = true;
		

	float normalx = 0.0f;
	float normaly = 0.0f;

	bool collided = false;
	int i = 0;

	//contra.iY += FRAMEHEIGHT / 2;
	while (!collided && i < listObject.size())
	{
		//contra van con trong mien va cham
		//va khong va cham voi doi tuong moi
		if (!inDomain ||( inDomain && _botGround->GetId() != listObject[i]->GetId()))
		{
			Box object = listObject[i]->GetBox();
			if (isCollide(contra, object, normalx, normaly))
			{
			#pragma region LAND
			//va cham voi dat
			if (listObject[i]->GetId() == 1)
			{
				//va cham thang dung
				if (normalx == 0 && normaly != 0)
				{
					//va cham bot
					if (normaly == 1)
					{
						collided = true;
						_botGround = listObject[i];
						BotLandColl(object.iY + FRAMEHEIGHT/2);
					}
					//va cham top
					else
					{
						//chua xet
					}
				}
				else if (normaly == 0 && normalx != 0)				//va cham phuong ngang
				{
					//chua xet
				}
				else
				{
					//chua xet
				}
			}
			#pragma endregion

			#pragma region WATER
			//va cham voi nuoc
			else if (listObject[i]->GetId() == 2)
			{
				//va cham thang dung
				if (normalx == 0 && normaly != 0)
				{
					//va cham bot
					if (normaly == 1)
					{
						collided = true;
						_botGround = listObject[i];
						BotWaterColl(object.iY + FRAMEHEIGHT/2);
					}
					//va cham top
					else
					{
						//chua xet
					}
				}
				else if (normaly == 0 && normalx != 0)				//va cham phuong ngang
				{
					//chua xet
				}
				else
				{
					//chua xet
				}
			}
			#pragma endregion
			}
		}

		//tinh object ben duoi
		if (!layAndFall)
		{
			Box object = listObject[i]->GetBox();
			if (contra.iY - contra.iHeight > object.iY
				&& contra.iX + contra.iWidth/2 > object.iX
				&& contra.iX + contra.iWidth/2 < object.iX + object.iWidth)
				layAndFall = true;
		}
		i++;
	}
	_layAndFall = layAndFall;

	//neu da thoat khoi mien va cham
	//va khong va cham voi doi tuong nao
	if (!inDomain && !collided)
	{
		_botGround = NULL;
		//NoColl(viewport + FRAMEHEIGHT)
		if (_y != VIEW_PORT_Y - SCREEN_HEIGHT + FRAMEHEIGHT/2)
			NoColl(VIEW_PORT_Y - SCREEN_HEIGHT + FRAMEHEIGHT/2);
	}


}
void CContra::TestSuperTurret(std::vector<CSuperTurret*> listObject)
{
	Box contra = GetBox();
	Box enemy;
	float normalx = 0;
	float normaly = 0;
	for (int i = 0; i < listObject.size(); i++)
	{
		enemy = listObject[i]->GetBox();
		//check collision here
		if (isCollide(contra, enemy, normalx, normaly))
		{
			if (normaly == 0)
			{
				if (normalx == -1)
				{
					_vectorX = 0;
				}
				else
				{
					_vectorX = 0;
				}
			}
		}
	}
}

void CContra::StartFall()
{
	_dwStartFall= GetTickCount();
	_dwFallTime = 0;
}
void CContra::ProcessFall()
{
	DWORD now = GetTickCount();
	_dwFallTime = now - _dwStartFall;
}
void CContra::EndFall()
{
	_dwStartFall = 0;
	_dwFallTime = 0;
}

CContra::~CContra()
{
}